package com.echat.serviceapigateway.security.service.impl;

import com.echat.commonlib.exception.exc.ValidateFailedException;
import com.echat.commonlib.util.SpringContextUtil;
import com.echat.serviceapigateway.security.config.CacheConfig;
import com.echat.serviceapigateway.security.constant.Constants;
import com.echat.serviceapigateway.security.mapper.AccessIpMapper;
import com.echat.serviceapigateway.security.model.network.AccessIp;
import com.echat.serviceapigateway.security.service.IpWhiteListService;
import com.echat.serviceapigateway.security.tool.SpringUtil;
import com.echat.serviceapigateway.security.tool.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * Created by chenmohan on 2018/09/05
 *
 * @description
 */
@Service
public class IpWhiteListServiceImpl implements IpWhiteListService {

    @Autowired
    AccessIpMapper accessIpMapper;

    @Override
    public boolean isExistIpWhiteList(Long userId, String ip) {
        if (userId == null) {
            throw new ValidateFailedException("parameter[userId] must not be null");
        }
        AccessIp accessIp = ((IpWhiteListService)SpringContextUtil.getBean(this.getClass())).getAccessIpByUserId(userId);
        String ips = accessIp.getIps().trim();
        if (accessIp == null || StringUtils.isEmpty(ips)) { //如果还没有配置过Ip,那么所有Ip都可以访问
            return true;
        }
        List<String> ipList = Arrays.asList(ips.split(Constants.COMMA));
        return ipList.contains(ip);
    }

    @Cacheable(value = CacheConfig.CACHE_IP_WHITE_LIST, key = "#userId")
    @Override
    public AccessIp getAccessIpByUserId(Long userId) {
        if (userId == null) {
            return null;
        }
        Example example = new Example(AccessIp.class);
        example.createCriteria().andEqualTo("userId", userId);
        AccessIp accessIp = accessIpMapper.selectOneByExample(example);
        return accessIp;
    }

    @Override
    public AccessIp createAccessIp(Long userId) {
        if (userId == null) {
            throw new ValidateFailedException("userId 不能为空");
        }
        LocalDateTime now = LocalDateTime.now();
        AccessIp insert = AccessIp.builder().userId(userId)
                .ips(Constants.EMPTY_STR)
                .createTime(now)
                .modifyTime(now).build();

        accessIpMapper.insertSelective(insert);
        return insert;
    }

    @CachePut(value = CacheConfig.CACHE_IP_WHITE_LIST, key = "#accessIp.userId")
    @Override
    public AccessIp updateAcceSSIp(AccessIp accessIp) {
        if (accessIp == null || accessIp.getUserId() == null || accessIp.getIps() == null) {
            throw new ValidateFailedException("accessIp缺少必要参数");
        }
        //检查ips是否合法
        String ips = accessIp.getIps();
        try {
            StringUtils.checkIps(ips);
        } catch (IllegalArgumentException e) {
            throw new ValidateFailedException("\"" + e.getMessage() + "\"不是合法的IP地址");
        }

        LocalDateTime now = LocalDateTime.now();
        accessIp.setModifyTime(now);
        //根据userId更新
        Example example = new Example(AccessIp.class);
        example.createCriteria().andEqualTo("userId",accessIp.getUserId());
        accessIpMapper.updateByExampleSelective(accessIp,example);

        //一旦更新了ip白名单,那么认证鉴权缓存也必须失效
        SpringUtil.clearUserAccessCahcer(accessIp.getUserId());
        return accessIp;
    }
}
